﻿using System.Text.RegularExpressions;

namespace GaurTest
{
    using System.Linq;
    using Gaur;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Tests for generic class Set
    /// </summary>
    [TestClass]
    public class Set
    {
        /// <summary>
        /// Gets or sets the test context which provides
        /// information about and functionality for the current test run.
        /// </summary>
        public TestContext TestContext
        {
            get;
            set; 
        }

        /// <summary>
        /// Constructors the test helper.
        /// </summary>
        /// <param name="set">The set containing elements.</param>
        /// <param name="els">The elements checked for existance in set.</param>
        /// <returns>True if set contains all elements and no other elements</returns>
        public bool ConstructorTestHelper(Set<int> set, params int[] els)
        {
            bool res = set.Count<int>() == els.Count<int>();

            foreach (int el in els)
            {
                res = res && set.Contains<int>(el);
            }

            return res;
        }

        /// <summary>
        /// Constructors the test.
        /// </summary>
        [TestMethod]
        public void ConstructorTest()
        {
            Set<int> s = new Set<int>();
            Set<int> s1 = new Set<int>(1);
            Set<int> s23 = new Set<int>(2, 3);
            Set<int> s123 = new Set<int>(1, 2, 3);
            Set<int> s234 = new Set<int>(2, 3, 4);
            Set<int> s12378 = new Set<int>(1, 2, 3, 7, 8);
            Set<int> s78 = new Set<int>(7, 8);
            Set<int> s1234 = new Set<int>(1, 2, 3, 4);
            Set<int> s5 = new Set<int>(5);

            Assert.IsTrue(this.ConstructorTestHelper(s));
            Assert.IsTrue(this.ConstructorTestHelper(s1, 1));
            Assert.IsTrue(this.ConstructorTestHelper(s23, 2, 3));
            Assert.IsTrue(this.ConstructorTestHelper(s123, 1, 2, 3));
            Assert.IsTrue(this.ConstructorTestHelper(s234, 2, 3, 4));
            Assert.IsTrue(this.ConstructorTestHelper(s12378, 1, 2, 3, 7, 8));
            Assert.IsTrue(this.ConstructorTestHelper(s78, 7, 8));
            Assert.IsTrue(this.ConstructorTestHelper(s1234, 1, 2, 3, 4));
            Assert.IsTrue(this.ConstructorTestHelper(s5, 5));
        }

        /// <summary>
        /// Test of union operator (+).
        /// </summary>
        [TestMethod]
        public void UnionTest()
        {
            Set<int> s = new Set<int>();
            Set<int> s1 = new Set<int>(1);
            Set<int> s23 = new Set<int>(2, 3);
            Set<int> s123 = new Set<int>(1, 2, 3);
            Set<int> s234 = new Set<int>(2, 3, 4);
            Set<int> s12378 = new Set<int>(1, 2, 3, 7, 8);
            Set<int> s78 = new Set<int>(7, 8);
            Set<int> s1234 = new Set<int>(1, 2, 3, 4);
            Set<int> s5 = new Set<int>(5);
            
            Assert.AreEqual<Set<int>>(s1 + s23 + s, s123); // {1} + {2, 3} + {} == {1, 2, 3}
            Assert.AreEqual<Set<int>>(s + s23 + s1 + s, s123); // {} + {2, 3} + {1} + {} == {1, 2, 3}

            Assert.AreEqual<Set<int>>(s23 + s234 + s, s234); // {2, 3} + {2, 3, 4} + {} == {2, 3, 4}

            Assert.AreEqual<Set<int>>(s123 + s78 + s, s12378); // {1, 2, 3} + {7, 8} + {} == {1, 2, 3, 7, 8}

            Assert.AreEqual<Set<int>>(s123 + s234 + s, s1234); // {1, 2, 3} + {2, 3, 4} + {} == {1, 2, 3, 4}

            Assert.AreEqual<Set<int>>(s + s123 + s1 + s23 + s234, s1234); // {} + {1, 2, 3} + {1} + {2, 3} + {2, 3, 4} == {1, 2, 3, 4}

            Assert.AreNotEqual<Set<int>>(s123 + s1 + s + s23 + s234 + s5, s1234); // {1, 2, 3} + {1} + {} + {2, 3} + {2, 3, 4} + {5} != {1, 2, 3, 4}
        }

        /// <summary>
        /// Test of difference operator (-).
        /// </summary>
        [TestMethod]
        public void DifferenceTest()
        {
            Set<int> s = new Set<int>();
            Set<int> s1 = new Set<int>(1);
            Set<int> s23 = new Set<int>(2, 3);
            Set<int> s123 = new Set<int>(1, 2, 3);
            Set<int> s234 = new Set<int>(2, 3, 4);
            Set<int> s12378 = new Set<int>(1, 2, 3, 7, 8);
            Set<int> s78 = new Set<int>(7, 8);
            Set<int> s1234 = new Set<int>(1, 2, 3, 4);
            Set<int> s5 = new Set<int>(5);

            Assert.AreEqual<Set<int>>(s1 - s23 - s, s1); // {1} - {2, 3} - {} == {1}
            Assert.AreEqual<Set<int>>(s - s23 - s1 - s, s); // {} - {2, 3} - {1} - {} == {}
            Assert.AreEqual<Set<int>>(s23 - s234 - s, s); // {2, 3} - {2, 3, 4} - {} == {}
            Assert.AreEqual<Set<int>>(s123 - s234, s1); // {1, 2, 3} - {2, 3, 4} == {1}
        }

        /// <summary>
        /// Test of intersection operator (*).
        /// </summary>
        [TestMethod]
        public void IntersectionTest()
        {
            Assert.AreEqual<Set<int>>(new Set<int>(1, 2, 3) * new Set<int>(2), new Set<int>(2));
        }

        /// <summary>
        /// Test of superset operator (>=).
        /// </summary>
        [TestMethod]
        public void SupersetTest()
        {
            Assert.IsTrue(new Set<int>(1, 2, 3) >= new Set<int>(2));
            Assert.IsFalse(new Set<int>(1, 3) >= new Set<int>(2));
        }

        /// <summary>
        /// Test of subset operator (<=).
        /// </summary>
        [TestMethod]
        public void SubsetTest()
        {
            Assert.IsTrue(new Set<int>(1, 2) <= new Set<int>(1, 2, 3));
            Assert.IsFalse(new Set<int>(1, 3) <= new Set<int>(2));
        }

        /// <summary>
        /// Test of equality operator (==).
        /// </summary>
        [TestMethod]
        public void EqualityTest()
        {
            Assert.IsTrue(new Set<int>(1, 2) == new Set<int>(1, 2));
            Assert.IsFalse(new Set<int>(1, 3) == new Set<int>(1, 3, 4));
        }

        /// <summary>
        /// Test of inequality operator (!=).
        /// </summary>
        [TestMethod]
        public void InequalityTest()
        {
            Assert.IsTrue(new Set<int>(1, 2) != new Set<int>(1, 2, 3));
            Assert.IsFalse(new Set<int>(1, 3) != new Set<int>(1, 3));
        }
    }
}
